package com.ezandroid.module.network.request;

import android.text.TextUtils;

import com.ezandroid.library.network.http.HttpLogger;
import com.ezandroid.library.network.http.request.Network;
import com.ezandroid.library.network.http.request.NetworkResponse;
import com.ezandroid.library.network.http.request.Request;
import com.ezandroid.library.network.http.request.RequestException;
import com.ezandroid.library.network.http.request.RequestManager;
import com.ezandroid.library.network.http.request.Response;
import com.ezandroid.module.network.response.HttpResponse;
import com.google.gson.JsonSyntaxException;

import org.json.JSONException;
import org.json.JSONObject;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * Request基类，统一处理一些操作
 *
 * @author markmjw
 * @date 2014-11-06
 */
public abstract class HttpBaseRequest<T> extends Request<T> {

    protected String mNodeName;

    protected HttpResponse<T> mResponse;

    public HttpBaseRequest(String url) {
        this(url, null);
    }

    public HttpBaseRequest(String url, String nodeName) {
        this(Method.GET, url, nodeName);
    }

    public HttpBaseRequest(int method, String url, String nodeName) {
        super(method, url);
        mResponse = new HttpResponse<>();
        mNodeName = nodeName;
    }

    /**
     * 异步方式执行HTTP请求
     *
     * @return this
     */
    public Request execute() {
        RequestManager.getInstance().getRequestQueue().add(this);
        return this;
    }

    /**
     * 同步方式执行HTTP请求
     *
     * @return this
     */
    public Request executeSync() {
        Network network = RequestManager.getInstance().getNetwork();
        try {
            Response<T> response = parseNetworkResponse(network.execute(this));
            deliverResponse(response.result);
        } catch (RequestException e) {
            deliverError(e);
        }
        return this;
    }

    /**
     * 异步方式执行HTTP请求
     *
     * @param tag 请求Tag
     * @return this
     */
    public Request execute(Object tag) {
        setTag(tag);
        return execute();
    }

    /**
     * 同步方式执行HTTP请求
     *
     * @param tag 请求Tag
     * @return this
     */
    public Request executeSync(Object tag) {
        setTag(tag);
        return executeSync();
    }

    @Override
    public Map<String, String> getHeaders() {
        // 默认不使用缓存
        Map<String, String> headers = new HashMap<>();
        headers.put("Cache-Control", "no-cache");
        return headers;
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        String content = new String(response.data, Charset.forName("UTF-8"));

        // 打印数据
        HttpLogger.printResponse(response.statusCode, getUrl(), content, response.networkTimeMs);

        try {
            // 解析状态
            JSONObject json = new JSONObject(content);
            mResponse.code = json.optInt("code", HttpResponse.CODE_FAILED);
            if (json.has("msg")) {
                mResponse.message = json.optString("msg", "");
            } else if (json.has("message")) {
                mResponse.message = json.optString("message", "");
            }

            // V2接口新增数据统一字段
            if (json.has("data")) {
                content = json.optString("data", content);
                if (!TextUtils.isEmpty(content)) {
                    json = new JSONObject(content);
                } else {
                    json = null;
                }
            }

            // 解析数据体
            T model = parseResponse(content, json);
            return Response.success(model);
        } catch (JsonSyntaxException e) {
            return Response.success(null);
        } catch (JSONException e) {
            return Response.error(new RequestException(e));
        }
    }

    @Override
    protected void deliverResponse(T t) {
        mResponse.url = getUrl();
        mResponse.data = t;
        onSuccess(mResponse);
    }

    @Override
    protected void deliverError(RequestException error) {
        onError(error);
    }

    protected abstract T parseResponse(String content, JSONObject json) throws JSONException;

    protected abstract void onSuccess(HttpResponse<T> response);

    protected abstract void onError(RequestException error);
}